package com.xixibaby.im;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.xixibaby.core.Assert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Slf4j
public class ImKit implements Im {

    //本地过期缓存
    private static final TimedCache<String, String> objects = CacheUtil.newTimedCache(5000000000L);

    @Autowired
    private ImProperties imProperties;

    private static final String FRIEND_URL = "/users/{}/contacts/users/{}";
    private static final String FRIEND_LIST_URL = "/users/{}/contacts/users";






    private <T> void http(String url,  Consumer<Map<String, Object>> params, Consumer<T> success, Class<T> clazz,boolean token){

        String format = StrUtil.format(imProperties.getDurl() + "/{}/{}", imProperties.getOrgName(), imProperties.getAppName());
        String url1 = format + url;
        log.info("环信SDK:[地址][{}]",url1);
        Map<String, Object> map = new HashMap<>();
        params.accept(map);

        String s = JSONObject.toJSONString(map);
        log.info("环信SDK:[参数][{}]",s);
        HttpRequest post = HttpUtil.createPost(url1).header("Content-Type", "application/json");
        if(token){
            String tokenStr = objects.get("huanxin_token");
            if(Assert.empty(tokenStr)){
                this.token(x -> objects.put("huanxin_token",x.getAccess_token()));
                tokenStr = objects.get("huanxin_token");
            }
            post.header("Authorization", "Bearer " + tokenStr);
        }
        HttpResponse response = post.body(s).execute();
        int status = response.getStatus();
        String execute = response.body();
        log.info("环信SDK:[返回][{}][{}]",status,execute);
        if(status == 200){
            T t = JSONObject.parseObject(execute, clazz);
            success.accept(t);
        }else{
            ImError imError = JSONObject.parseObject(execute, ImError.class);
            log.info("环信SDK错误：[{}][{}][{}]",status,imError.getError(),imError.getError_description());
        }

    }

    private <T> void httpNoToken(String url,  Consumer<Map<String, Object>> params, Consumer<T> success, Class<T> clazz){
        this.http(url, params, success, clazz,false);
    }

    private <T> void http(String url, Consumer<Map<String, Object>> params, Consumer<List<T>> success, Class<T> clazz){
        this.http(url, params, x -> {
            List<JSONObject> entities = x.getEntities();
            List<T> collect = entities.stream().map(obj -> JSONObject.parseObject(obj.toJSONString(), clazz)).collect(Collectors.toList());
            success.accept(collect);
        }, ImResult.class,true);
    }


    private void token(Consumer<ImToken> success) {
        this.httpNoToken("/token", x -> {
            x.put("client_id",imProperties.getClient_id());
            x.put("grant_type",imProperties.getGrant_type());
            x.put("client_secret",imProperties.getClient_secret());
        },success,ImToken.class);
    }

    @Override
    public void user(ImUserInfo users,Consumer<ImUserInfo> success) {
        this.http("/users", x -> {
            x.put("username",users.getUsername());
            x.put("password",users.getPassword());
            x.put("nickname",users.getNickname());
        },x -> success.accept(x.get(0)),ImUserInfo.class);
    }

    @Override
    public void friend(String ownName, String friendName) {
        String format = StrUtil.format(FRIEND_URL, ownName, friendName);
        this.http(format, x -> {}, x -> {}, ImUserInfo.class);
        //users/{owner_username}/contacts/users/{friend_username}
    }

    @Override
    public void customMessages(String type, String[] target, Consumer<Map<String, String>> exts) {
        this.http("/messages", x -> {
            x.put("target_type","users");
            x.put("target",target);
            Map<String, String> map = new HashMap<>();
            exts.accept(map);
            x.put("from",type);
            x.put("msg",new Msg(type, map));
        }, x -> {}, ImResult.class,true);
    }

    public void order(String target, Consumer<Map<String, String>> exts) {
       this.customMessages("SYSTEM_USER_ORDER_MESSAGE",new String[]{target},exts);
    }

    public void aunt(String target, Consumer<Map<String, String>> exts) {
        this.customMessages("SYSTEM_USER_AUNT_MESSAGE",new String[]{target},exts);
    }

    public void backlog(String target, Consumer<Map<String, String>> exts) {
        this.customMessages("SYSTEM_USER_BACKLOG_MESSAGE",new String[]{target},exts);
    }

    public void notice(String target, Consumer<Map<String, String>> exts) {
        this.customMessages("SYSTEM_USER_NOTICE_MESSAGE",new String[]{target},exts);
    }


    @Override
    public void user(Long id, Consumer<ImUserInfo> success) {
        String s = id.toString();
        ImUserInfo imUserInfo = new ImUserInfo(s, s, s);
        this.user(imUserInfo,success);
    }
}
